#include<iostream>
#include<functional>
#include<vector>
#include<memory>
#include<unordered_map>
#include<unistd.h>

using Task = std::function<void()>;
using Release = std::function<void()>;


class TimerTask
{
public:
    TimerTask(uint64_t id,uint32_t timeout,const Task& task)
    :_id(id),_timeout(timeout),_task(task),_cancel(false) //cancel默认为没有取消任务
    {
        
    }

    void SetRelease(const Release& cb)
    {
        _release = cb;
    }

    uint32_t GetTimeOut()
    {
        return _timeout;
    }

    void Cancel()
    {
        _cancel = true;
    }



    ~TimerTask()
    {
        if(_cancel == false) //如果没有被取消,就执行任务
            _task();
        _release();
    }


private:
    uint64_t _id; //定时任务id
    uint32_t _timeout; //定时任务的超时时间
    Task _task; //定时任务执行操作
    Release _release; //定时任务释放操作
    bool _cancel; //任务是否被取消
};

using _PtrTask = std::shared_ptr<TimerTask>; 
using _WeakPtr = std::weak_ptr<TimerTask>;

class TimeWheel
{
public:
    TimeWheel(int tick = 0,int capacity = 60):_tick(tick),_capacity(capacity),_wheel(_capacity)
    {

    }

    void Remove(uint64_t id)
    {
        auto it = _timers.find(id);
        if(it != _timers.end())
        {
            _timers.erase(it);
        }
    }



    void TimerTaskAdd(uint64_t _id,uint32_t _timeout,const Task& _task) //添加定时任务
    {
        _PtrTask _sptr(new TimerTask(_id,_timeout,_task)); 
        _sptr->SetRelease(std::bind(&TimeWheel::Remove,this,_id)); //设置清除方法
        _wheel[(_tick + _timeout) % _capacity].push_back(_sptr); //插入到时间轮中

        _timers[_id] = _WeakPtr(_sptr);//插入到哈希中


    }

    void TimerTaskRefresh(uint64_t _id) //延迟/刷新定时任务
    {
        auto it = _timers.find(_id);
        if(it == _timers.end())
        {
            return;
        }

        _PtrTask _sptr = it->second.lock();
        _wheel[(_tick + _sptr->GetTimeOut()) % _capacity].push_back(_sptr); 
        //把shared_ptr拷贝之后再次加入_wheel中
        //使得该位置的TimerTask的shard_ptr的引用计数++,从而延缓了调用析构的时间,达到任务执行时间刷新的效果
    }

    void Run()
    {
        _tick = (_tick + 1) % _capacity;
        _wheel[_tick].clear();
    }

    void TimerCancel(int _id)
    {
        auto iter = _timers.find(_id);
        if(iter == _timers.end())
        {
            return;
        }
        
        _PtrTask _sptr = iter->second.lock();
        _sptr->Cancel();
        
    }



    ~TimeWheel()
    {}



private:
    int _tick; //秒针
    int _capacity; //表盘最大延迟时间
    std::vector<std::vector<_PtrTask>> _wheel;//时钟轮
    std::unordered_map<uint64_t,_WeakPtr> _timers; //方便寻找TimeTask对象

};

// class Test
// {
// public:
//     Test()
//     {
//         std::cout << "构造" << std::endl;
//     }
//     ~Test()
//     {
//         std::cout << "析构" <<std::endl;
//     }
// };

// void Delete(Test* t)
// {
//     delete t;
// }




// int main()
// {
//     Test* t = new Test();
//     TimeWheel _TW;
//     _TW.TimerTaskAdd(1,5,std::bind(Delete,t));
//     for(int i = 0;i<5;i++)
//     {
//         sleep(1);
//         _TW.TimerTaskRefresh(1);
//         _TW.Run();

//     }

//     _TW.TimerCancel(1);

//     while(1)
//     {
//         sleep(1);
//         std::cout << "---------" <<std::endl;
//         _TW.Run();
//     }


//     return 0;
// }


